////////////////////////////////////////////////////////////////////////////////
// Filename: rendertextureclass.cpp
////////////////////////////////////////////////////////////////////////////////
#include "rendertextureclass.h"


RenderTextureClass::RenderTextureClass()
{
	m_renderTargetTexture = 0;
	m_renderTargetView = 0;
	m_shaderResourceView = 0;
	mDepthStencilTexture = 0;
	mDepthMapSRV = 0;
	mDepthMapDSV = 0;

	mDepthStencilTexture2 = 0;
	mDepthMapSRV2 = 0;
	mDepthMapDSV2 = 0;
}


RenderTextureClass::RenderTextureClass(const RenderTextureClass& other)
{
}


RenderTextureClass::~RenderTextureClass()
{
}


bool RenderTextureClass::Initialize(ID3D10Device* device, int textureWidth, int textureHeight)
{
	HRESULT result;
	result = buildColorMap(device, textureWidth, textureHeight);
	if (!result)
	{
		return false;
	}

	result = buildDepthMap(device, textureWidth, textureHeight);
	if (!result)
	{
		return false;
	}

	result = buildDepthMap2(device, textureWidth, textureHeight);
	if (!result)
	{
		return false;
	}
	return true;
}


void RenderTextureClass::Shutdown()
{
	if(m_shaderResourceView)
	{
		m_shaderResourceView->Release();
		m_shaderResourceView = 0;
	}

	if(m_renderTargetView)
	{
		m_renderTargetView->Release();
		m_renderTargetView = 0;
	}

	if(m_renderTargetTexture)
	{
		m_renderTargetTexture->Release();
		m_renderTargetTexture = 0;
	}

	if(mDepthStencilTexture)
	{
		mDepthStencilTexture->Release();
		mDepthStencilTexture = 0;
	}
	if(mDepthMapSRV)
	{
		mDepthMapSRV->Release();
		mDepthMapSRV = 0;
	}
	if(mDepthMapDSV)
	{
		mDepthMapDSV->Release();
		mDepthMapDSV = 0;
	}

	if(mDepthStencilTexture2)
	{
		mDepthStencilTexture2->Release();
		mDepthStencilTexture2 = 0;
	}
	if(mDepthMapSRV2)
	{
		mDepthMapSRV2->Release();
		mDepthMapSRV2 = 0;
	}
	if(mDepthMapDSV2)
	{
		mDepthMapDSV2->Release();
		mDepthMapDSV2 = 0;
	}
	return;
}


void RenderTextureClass::SetRenderTarget(ID3D10Device* device, ID3D10DepthStencilView* depthStencilView)
{
	// Bind the render target view and depth stencil buffer to the output render pipeline.
	device->OMSetRenderTargets(1, &m_renderTargetView, depthStencilView);
	
	return;
}

void RenderTextureClass::SetDepthStencil(ID3D10Device* device, ID3D10RenderTargetView* renderTargetView)
{
	// Bind the render target view and depth stencil buffer to the output render pipeline.
	ID3D10RenderTargetView* targetView[1] = {0};
	device->OMSetRenderTargets(1, targetView, mDepthMapDSV);

	return;
}

void RenderTextureClass::SetDepthStencil2(ID3D10Device* device, ID3D10RenderTargetView* renderTargetView)
{
	// Bind the render target view and depth stencil buffer to the output render pipeline.
	ID3D10RenderTargetView* targetView[1] = {0};
	device->OMSetRenderTargets(1, targetView, mDepthMapDSV2);

	return;
}

void RenderTextureClass::ClearRenderTarget(ID3D10Device* device, ID3D10DepthStencilView* depthStencilView, 
										   float red, float green, float blue, float alpha)
{
	float color[4];


	// Setup the color to clear the buffer to.
	color[0] = red;
	color[1] = green;
	color[2] = blue;
	color[3] = alpha;

	// Clear the back buffer.
	device->ClearRenderTargetView(m_renderTargetView, color);
    
	// Clear the depth buffer.
	device->ClearDepthStencilView(depthStencilView, D3D10_CLEAR_DEPTH, 1.0f, 0);

	return;
}

void RenderTextureClass::ClearDepthStencil(ID3D10Device* device, ID3D10RenderTargetView* renderTargetView, 
										   float red, float green, float blue, float alpha)
{
	float color[4];


	// Setup the color to clear the buffer to.
	color[0] = red;
	color[1] = green;
	color[2] = blue;
	color[3] = alpha;

	// Clear the back buffer.
	device->ClearRenderTargetView(renderTargetView, color);

	// Clear the depth buffer.
	device->ClearDepthStencilView(mDepthMapDSV, D3D10_CLEAR_DEPTH, 1.0f, 0);

	return;
}

void RenderTextureClass::ClearDepthStencil2(ID3D10Device* device, ID3D10RenderTargetView* renderTargetView, 
										   float red, float green, float blue, float alpha)
{
	float color[4];


	// Setup the color to clear the buffer to.
	color[0] = red;
	color[1] = green;
	color[2] = blue;
	color[3] = alpha;

	// Clear the back buffer.
	device->ClearRenderTargetView(renderTargetView, color);

	// Clear the depth buffer.
	device->ClearDepthStencilView(mDepthMapDSV2, D3D10_CLEAR_DEPTH, 1.0f, 0);

	return;
}

ID3D10ShaderResourceView* RenderTextureClass::GetShaderResourceView()
{
	return m_shaderResourceView;
}

ID3D10ShaderResourceView* RenderTextureClass::GetDepthStencilView()
{
	return mDepthMapSRV;
}

ID3D10ShaderResourceView* RenderTextureClass::GetDepthStencilView2()
{
	return mDepthMapSRV2;
}

bool RenderTextureClass::buildDepthMap(ID3D10Device* device, int textureWidth, int textureHeight)
{
	D3D10_TEXTURE2D_DESC texDesc;
	HRESULT result;

	ZeroMemory(&texDesc, sizeof(texDesc));
	texDesc.Width     = textureWidth;
	texDesc.Height    = textureHeight;
	texDesc.MipLevels = 1;
	texDesc.ArraySize = 1;
	texDesc.Format    = DXGI_FORMAT_R32_TYPELESS;
	texDesc.SampleDesc.Count   = 1;  
	texDesc.SampleDesc.Quality = 0;  
	texDesc.Usage          = D3D10_USAGE_DEFAULT;
	texDesc.BindFlags      = D3D10_BIND_DEPTH_STENCIL | D3D10_BIND_SHADER_RESOURCE;
	texDesc.CPUAccessFlags = 0; 
	texDesc.MiscFlags      = 0;

	result = device->CreateTexture2D(&texDesc, 0, &mDepthStencilTexture);
	if(FAILED(result))
	{
		return false;
	}

	D3D10_DEPTH_STENCIL_VIEW_DESC dsvDesc;
	dsvDesc.Format = DXGI_FORMAT_D32_FLOAT;
	dsvDesc.ViewDimension = D3D10_DSV_DIMENSION_TEXTURE2D;
	dsvDesc.Texture2D.MipSlice = 0;
	result = device->CreateDepthStencilView(mDepthStencilTexture, &dsvDesc, &mDepthMapDSV);
	if(FAILED(result))
	{
		return false;
	}

	D3D10_SHADER_RESOURCE_VIEW_DESC srvDesc;
	srvDesc.Format = DXGI_FORMAT_R32_FLOAT;
	srvDesc.ViewDimension = D3D10_SRV_DIMENSION_TEXTURE2D;
	srvDesc.Texture2D.MipLevels = texDesc.MipLevels;
	srvDesc.Texture2D.MostDetailedMip = 0;
	result = device->CreateShaderResourceView(mDepthStencilTexture, &srvDesc, &mDepthMapSRV);
	if(FAILED(result))
	{
		return false;
	}

	return true;
}


bool RenderTextureClass::buildDepthMap2(ID3D10Device* device, int textureWidth, int textureHeight)
{
	D3D10_TEXTURE2D_DESC texDesc;
	HRESULT result;

	ZeroMemory(&texDesc, sizeof(texDesc));
	texDesc.Width     = textureWidth;
	texDesc.Height    = textureHeight;
	texDesc.MipLevels = 1;
	texDesc.ArraySize = 1;
	texDesc.Format    = DXGI_FORMAT_R32_TYPELESS;
	texDesc.SampleDesc.Count   = 1;  
	texDesc.SampleDesc.Quality = 0;  
	texDesc.Usage          = D3D10_USAGE_DEFAULT;
	texDesc.BindFlags      = D3D10_BIND_DEPTH_STENCIL | D3D10_BIND_SHADER_RESOURCE;
	texDesc.CPUAccessFlags = 0; 
	texDesc.MiscFlags      = 0;

	result = device->CreateTexture2D(&texDesc, 0, &mDepthStencilTexture2);
	if(FAILED(result))
	{
		return false;
	}

	D3D10_DEPTH_STENCIL_VIEW_DESC dsvDesc;
	dsvDesc.Format = DXGI_FORMAT_D32_FLOAT;
	dsvDesc.ViewDimension = D3D10_DSV_DIMENSION_TEXTURE2D;
	dsvDesc.Texture2D.MipSlice = 0;
	result = device->CreateDepthStencilView(mDepthStencilTexture2, &dsvDesc, &mDepthMapDSV2);
	if(FAILED(result))
	{
		return false;
	}

	D3D10_SHADER_RESOURCE_VIEW_DESC srvDesc;
	srvDesc.Format = DXGI_FORMAT_R32_FLOAT;
	srvDesc.ViewDimension = D3D10_SRV_DIMENSION_TEXTURE2D;
	srvDesc.Texture2D.MipLevels = texDesc.MipLevels;
	srvDesc.Texture2D.MostDetailedMip = 0;
	result = device->CreateShaderResourceView(mDepthStencilTexture2, &srvDesc, &mDepthMapSRV2);
	if(FAILED(result))
	{
		return false;
	}

	return true;
}


bool RenderTextureClass::buildColorMap(ID3D10Device* device, int textureWidth, int textureHeight)
{
	D3D10_TEXTURE2D_DESC textureDesc;
	HRESULT result;
	D3D10_RENDER_TARGET_VIEW_DESC renderTargetViewDesc;
	D3D10_SHADER_RESOURCE_VIEW_DESC shaderResourceViewDesc;


	// Initialize the render target texture description.
	ZeroMemory(&textureDesc, sizeof(textureDesc));

	// Setup the render target texture description.
	textureDesc.Width = textureWidth;
	textureDesc.Height = textureHeight;
	textureDesc.MipLevels = 1;
	textureDesc.ArraySize = 1;
	textureDesc.Format = DXGI_FORMAT_R32G32B32A32_FLOAT;
	textureDesc.SampleDesc.Count = 1;
	textureDesc.Usage = D3D10_USAGE_DEFAULT;
	textureDesc.BindFlags = D3D10_BIND_RENDER_TARGET | D3D10_BIND_SHADER_RESOURCE;
	textureDesc.CPUAccessFlags = 0;
	textureDesc.MiscFlags = 0;

	// Create the render target texture.
	result = device->CreateTexture2D(&textureDesc, NULL, &m_renderTargetTexture);
	if(FAILED(result))
	{
		return false;
	}

	// Setup the description of the render target view.
	renderTargetViewDesc.Format = textureDesc.Format;
	renderTargetViewDesc.ViewDimension = D3D10_RTV_DIMENSION_TEXTURE2D;
	renderTargetViewDesc.Texture2D.MipSlice = 0;

	// Create the render target view.
	result = device->CreateRenderTargetView(m_renderTargetTexture, &renderTargetViewDesc, &m_renderTargetView);
	if(FAILED(result))
	{
		return false;
	}

	// Setup the description of the shader resource view.
	shaderResourceViewDesc.Format = textureDesc.Format;
	shaderResourceViewDesc.ViewDimension = D3D10_SRV_DIMENSION_TEXTURE2D;
	shaderResourceViewDesc.Texture2D.MostDetailedMip = 0;
	shaderResourceViewDesc.Texture2D.MipLevels = 1;

	// Create the shader resource view.
	result = device->CreateShaderResourceView(m_renderTargetTexture, &shaderResourceViewDesc, &m_shaderResourceView);
	if(FAILED(result))
	{
		return false;
	}

	return true;
}